package com.pactera.madp.cp.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pactera.madp.common.data.tenant.TenantContextHolder;
import com.pactera.madp.cp.api.dto.WorkMassContactGroupDto;
import com.pactera.madp.cp.api.dto.crm.CrmCustomQueryConditionDTO;
import com.pactera.madp.cp.api.dto.workroom.WorkMassMsgDetailsPageDTO;
import com.pactera.madp.cp.api.dto.workroom.WorkMassMsgPageDTO;
import com.pactera.madp.cp.api.em.WorkMassEnum;
import com.pactera.madp.cp.api.em.workupdatetime.TypeEnum;
import com.pactera.madp.cp.api.entity.*;
import com.pactera.madp.cp.api.entity.crm.WorkCustomInfoEntity;
import com.pactera.madp.cp.api.entity.workroom.WorkMassContactEntity;
import com.pactera.madp.cp.api.entity.workroom.WorkMassMsgEntity;
import com.pactera.madp.cp.api.feign.RemoteDeptService;
import com.pactera.madp.cp.api.page.SubPage;
import com.pactera.madp.cp.api.vo.workroom.*;
import com.pactera.madp.cp.common.util.PageUtil;
import com.pactera.madp.cp.common.util.WxApiUtils;
import com.pactera.madp.cp.handler.CorpContextHolder;
import com.pactera.madp.cp.mapper.workroom.WorkMassMsgMapper;
import com.pactera.madp.cp.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.internal.StringUtil;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * WorkMassMsgServiceImpl
 *
 * @author jun
 * @version 1.0
 * 2021/7/13 10:26
 **/
@Service
@Slf4j
@AllArgsConstructor
public class WorkMassMsgServiceImpl extends ServiceImpl<WorkMassMsgMapper, WorkMassMsgEntity> implements WorkMassMsgService {

    private final WorkEmployeeServiceImpl workEmployeeService;
    private final WorkEmployeeDepartmentServiceImpl workEmployeeDepartmentService;
    private final WorkMassContactServiceImpl workMassContactService;
    private final  IContactService contactService;
    private final WorkRoomServiceImpl workRoomService;
    private final IWorkUpdateTimeService workUpdateTimeService;
    private final RemoteDeptService remoteDeptService;
    private final IWorkDeptService workDeptService;
    private final IWorkContactEmployeeService workContactEmployeeService;
    private final WorkCustomInfoService workCustomInfoService;

    @Override
    public void syncGroupMsgList(Integer types) {
        List<WorkMassMsgEntity> list = list(Wrappers.<WorkMassMsgEntity>lambdaQuery().select(WorkMassMsgEntity::getCreateTime,WorkMassMsgEntity::getSendTime)
                .eq(WorkMassMsgEntity::getMsgType,types).orderByDesc(WorkMassMsgEntity::getCreateTime));
        if (list.isEmpty()){
            Map<String, Object> groupMsg = new HashMap<>();
            groupMsg.put("chat_type",types == 1  ? "single" : "group");
            long startTime = DateUtil.offsetDay(new Date(),-30).getTime() / 1000;
            groupMsg.put("start_time", startTime);
            long endTime = DateUtil.date().getTime() / 1000;
            groupMsg.put("end_time",endTime);
            String groupesult = WxApiUtils.getGroupmsgList( CorpContextHolder.getCorpId(), JSONObject.toJSONString(groupMsg));
            if (StrUtil.isBlank(groupesult)){
                return;
            }
            JSONObject object = JSONObject.parseObject(groupesult);
            JSONArray groupMsgList = JSONArray.parseArray(object.getString("group_msg_list"));

            getGroupMsg(object,groupMsgList,startTime,endTime,types);
            List<Object> objectList = groupMsgList.stream().distinct().collect(Collectors.toList());

            for (int i = 0; i < objectList.size(); i++) {
                JSONObject jsonObject = JSONObject.parseObject(objectList.get(i).toString());
                WorkMassMsgEntity msgEntity = new WorkMassMsgEntity();
                msgEntity.setMsgId(jsonObject.getString("msgid"));
                msgEntity.setSendTime(LocalDateTime.ofEpochSecond(jsonObject.getLong("create_time"),0, ZoneOffset.ofHours(8)));
                msgEntity.setCreator(jsonObject.getString("creator"));
                msgEntity.setCreateType(jsonObject.getIntValue("create_type"));
                HashMap<String, Object> hashMap = new HashMap<>();
                StringBuilder sb = new StringBuilder();
                if (!StringUtil.isBlank(jsonObject.getString("text"))){
                    sb.append(1).append(",");
                    hashMap.put("text",JSONObject.parseObject(jsonObject.getString("text")));
                }
                JSONArray attachments = JSONArray.parseArray(jsonObject.getString("attachments"));
                List<Object> images = new LinkedList<>();
                List<Object> links = new LinkedList<>();
                List<Object> miniprograms = new LinkedList<>();
                List<Object> videos = new LinkedList<>();

                for (int j = 0; j < attachments.size(); j++) {
                    JSONObject attach = JSONObject.parseObject(attachments.get(j).toString());
                    String msgtype = attach.getString("msgtype");
                    switch (msgtype){
                        case "image":
                            images.add(attach.getString("image"));
                            break;
                        case "link":
                            links.add(attach.getString("link"));
                            break;
                        case "miniprogram":
                            miniprograms.add(attach.getString("miniprogram"));
                            break;
                        case "video":
                            videos.add(attach.getString("video"));
                            break;
                    }
                }
                if (!images.isEmpty()){
                    sb.append(2).append(",");
                }
                if (!links.isEmpty()){
                    sb.append(3).append(",");
                }
                if (!miniprograms.isEmpty()){
                    sb.append(4).append(",");
                }
                if (!videos.isEmpty()){
                    sb.append(5).append(",");
                }
                msgEntity.setType(sb.toString().substring(0, sb.toString().length() - 1));
                hashMap.put("image",images);
                hashMap.put("link",links);
                hashMap.put("miniprogram",miniprograms);
                hashMap.put("video",videos);
                msgEntity.setMessages(JSONObject.toJSONString(hashMap));


                Map<String, Object> task = new HashMap<>();
                task.put("msgid",jsonObject.getString("msgid"));
                String result = WxApiUtils.getGroupmsgTask( CorpContextHolder.getCorpId(), JSONObject.toJSONString(task));
                JSONObject taskResult = JSONObject.parseObject(result);
                JSONArray taskList = JSONArray.parseArray(taskResult.getString("task_list"));
                int deliveryCount = 0;
                int lossCount = 0;
                getTaskList(taskResult,jsonObject.getString("msgid"),taskList);
                List<Object> collect = taskList.stream().distinct().collect(Collectors.toList());
                List<Object> objects = null;
                List<Object> sends = new LinkedList<>();
                for (int j = 0; j < collect.size(); j++) {
                    JSONObject taskk = JSONObject.parseObject(collect.get(j).toString());
                    Map<String, Object> send = new HashMap<>();
                    send.put("msgid",jsonObject.getString("msgid"));
                    send.put("userid",taskk.getString("userid"));

                    String sendResult = WxApiUtils.getGroupmsgSendResult( CorpContextHolder.getCorpId(), JSONObject.toJSONString(send));
                    JSONObject sendResults = JSONObject.parseObject(sendResult);
                    JSONArray sendList = JSONArray.parseArray(sendResults.getString("send_list"));
                    for (int k = 0; k < sendList.size(); k++) {
                        JSONObject sendd = JSONObject.parseObject(sendList.get(k).toString());
                        if (sendd.getInteger("status").equals(1)){
                            deliveryCount++;
                        }else {
                            lossCount++;
                        }
                    }
                    boolean flag = true;
                    while (flag){
                        flag = getSendList(deliveryCount, lossCount, sendResults,taskk.getString("userid"),sendList);
                    }
                     objects = sendList.stream().distinct().collect(Collectors.toList());
                     sends.addAll(objects);
                }

                msgEntity.setDeliveryCount(deliveryCount);
                msgEntity.setLoseCount(lossCount);
                msgEntity.setTenantId( TenantContextHolder.getTenantId());
                msgEntity.setCreateTime(LocalDateTime.now());
                msgEntity.setMsgType(types);
                msgEntity.setCorpId( CorpContextHolder.getCorpId());
                save(msgEntity);

                /**
                 * 新增群发客户/群信息
                 */
                WorkMassMsgEntity one = getOne(Wrappers.<WorkMassMsgEntity>lambdaQuery().eq(WorkMassMsgEntity::getMsgId, msgEntity.getMsgId()));
                workMassContactService.remove(new LambdaQueryWrapper<WorkMassContactEntity>()
                        .eq(WorkMassContactEntity::getMassId,one.getId()));
                for (int j = 0; j < sends.size(); j++) {
                    JSONObject send = JSONObject.parseObject(sends.get(j).toString());
                    WorkMassContactEntity entity = new WorkMassContactEntity();
                    entity.setMassId(one.getId());
                    entity.setExternalUserid(send.getString("external_userid"));
                    try {
                        entity.setSendTime(LocalDateTime.ofEpochSecond(send.getLong("send_time"),0, ZoneOffset.ofHours(8)));
                    }catch (NullPointerException e){
                        entity.setSendTime(null);
                    }
                    entity.setUserid(send.getString("userid"));
                    entity.setStatus(send.getInteger("status"));
                    entity.setChatId(send.getString("chat_id"));
                    workMassContactService.save(entity);
                }
            }

        }else {
            LocalDateTime createTime = list.get(0).getSendTime();
            DateTime date = DateUtil.date(createTime);
            final long nowTime = DateTime.now().getTime() / 1000;
            long endTime = 0;
            if (DateUtil.offsetDay(date, 30).getTime() > DateTime.now().getTime()){
                endTime = DateTime.now().getTime() / 1000;
            }else {
                endTime = DateUtil.offsetDay(date, 30).getTime() / 1000;
            }
            long startTime = createTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000 + 1;

            //获取企业的全部群发记录
            List<WorkMassContactGroupDto> strings = new LinkedList<>();
             strings = synGroupMsgList(types,startTime,endTime,endTime,strings,nowTime);
            if (strings.isEmpty()){
                return;
            }else {
                strings.forEach(groupmsgList->{
                    JSONObject groupResult = JSONObject.parseObject(groupmsgList.getText());
                    JSONArray groupMsgList = JSONArray.parseArray(groupResult.getString("group_msg_list"));
                    if (groupMsgList.isEmpty()){
                        return;
                    }
                    groupMsgList.sort(Comparator.comparing(obj -> ((JSONObject) obj).getBigDecimal("create_time")));

                    getGroupMsg(groupResult,groupMsgList,groupmsgList.getStartTime(),groupmsgList.getEndTime(),types);
                    List<Object> objectList = groupMsgList.stream().distinct().collect(Collectors.toList());

                    for (int i = 0; i < objectList.size(); i++) {
                        JSONObject jsonObject = JSONObject.parseObject(objectList.get(i).toString());
                        WorkMassMsgEntity msgEntity = new WorkMassMsgEntity();
                        msgEntity.setMsgId(jsonObject.getString("msgid"));
                        msgEntity.setSendTime(LocalDateTime.ofEpochSecond(jsonObject.getLong("create_time"),0, ZoneOffset.ofHours(8)));
                        msgEntity.setCreator(jsonObject.getString("creator"));
                        msgEntity.setCreateType(jsonObject.getIntValue("create_type"));
                        HashMap<String, Object> hashMap = new HashMap<>();
                        StringBuilder sb = new StringBuilder();
                        if (!StringUtil.isBlank(jsonObject.getString("text"))){
                            sb.append(1).append(",");
                            hashMap.put("text",JSONObject.parseObject(jsonObject.getString("text")));
                        }
                        JSONArray attachments = JSONArray.parseArray(jsonObject.getString("attachments"));
                        List<Object> images = new LinkedList<>();
                        List<Object> links = new LinkedList<>();
                        List<Object> miniprograms = new LinkedList<>();
                        List<Object> videos = new LinkedList<>();

                        for (int j = 0; j < attachments.size(); j++) {
                            JSONObject attach = JSONObject.parseObject(attachments.get(j).toString());
                            String msgtype = attach.getString("msgtype");
                            switch (msgtype){
                                case "image":
                                    images.add(attach.getString("image"));
                                    break;
                                case "link":
                                    links.add(attach.getString("link"));
                                    break;
                                case "miniprogram":
                                    miniprograms.add(attach.getString("miniprogram"));
                                    break;
                                case "video":
                                    videos.add(attach.getString("video"));
                                    break;
                            }
                        }
                        if (!images.isEmpty()){
                            sb.append(2).append(",");
                        }
                        if (!links.isEmpty()){
                            sb.append(3).append(",");
                        }
                        if (!miniprograms.isEmpty()){
                            sb.append(4).append(",");
                        }
                        if (!videos.isEmpty()){
                            sb.append(5).append(",");
                        }
                        msgEntity.setType(sb.toString().substring(0, sb.toString().length() - 1));
                        hashMap.put("image",images);
                        hashMap.put("link",links);
                        hashMap.put("miniprogram",miniprograms);
                        hashMap.put("video",videos);
                        msgEntity.setMessages(JSONObject.toJSONString(hashMap));

                        // 获取群发成员发送任务列表
                        Map<String, Object> task = new HashMap<>();
                        task.put("msgid",jsonObject.getString("msgid"));
                        String result = WxApiUtils.getGroupmsgTask( CorpContextHolder.getCorpId(), JSONObject.toJSONString(task));
                        JSONObject taskResult = JSONObject.parseObject(result);
                        JSONArray taskList = JSONArray.parseArray(taskResult.getString("task_list"));
                        int deliveryCount = 0;
                        int lossCount = 0;
                        getTaskList(taskResult,jsonObject.getString("msgid"),taskList);
                        List<Object> collect = taskList.stream().distinct().collect(Collectors.toList());
                        List<Object> objects = null;
                        List<Object> sends = new LinkedList<>();
                        for (int j = 0; j < collect.size(); j++) {
                            JSONObject taskk = JSONObject.parseObject(collect.get(j).toString());
                            Map<String, Object> send = new HashMap<>();
                            send.put("msgid",jsonObject.getString("msgid"));
                            send.put("userid",taskk.getString("userid"));

                            //获取企业群发成员执行结果
                            String sendResult = WxApiUtils.getGroupmsgSendResult( CorpContextHolder.getCorpId(), JSONObject.toJSONString(send));
                            JSONObject sendResults = JSONObject.parseObject(sendResult);
                            JSONArray sendList = JSONArray.parseArray(sendResults.getString("send_list"));
                            for (int k = 0; k < sendList.size(); k++) {
                                JSONObject sendd = JSONObject.parseObject(sendList.get(k).toString());
                                if (sendd.getInteger("status").equals(1)){
                                    deliveryCount++;
                                }else {
                                    lossCount++;
                                }
                            }
                            boolean flag = true;
                            while (flag){
                                flag = getSendList(deliveryCount, lossCount, sendResults,taskk.getString("userid"),sendList);
                            }
                            objects = sendList.stream().distinct().collect(Collectors.toList());
                            sends.addAll(objects);
                        }

                        msgEntity.setDeliveryCount(deliveryCount);
                        msgEntity.setLoseCount(lossCount);
                        msgEntity.setTenantId( TenantContextHolder.getTenantId());
                        msgEntity.setCreateTime(LocalDateTime.now());
                        msgEntity.setMsgType(types);
                        msgEntity.setCorpId( CorpContextHolder.getCorpId());
                        WorkMassMsgEntity one = getOne(Wrappers.<WorkMassMsgEntity>lambdaQuery().eq(WorkMassMsgEntity::getMsgId, msgEntity.getMsgId()));
                        if (one == null){
                            save(msgEntity);
                        }else {
                            msgEntity.setId(one.getId());
                            msgEntity.setCreateTime(null);
                            msgEntity.setUpdateTime(LocalDateTime.now());
                            updateById(msgEntity);
                        }

                        /**
                         * 新增群发客户/群信息
                         */
                        one = getOne(Wrappers.<WorkMassMsgEntity>lambdaQuery()
                                .eq(WorkMassMsgEntity::getMsgId, msgEntity.getMsgId()));
                        workMassContactService.remove(new LambdaQueryWrapper<WorkMassContactEntity>()
                                .eq(WorkMassContactEntity::getMassId,one.getId()));
                        for (int j = 0; j < sends.size(); j++) {
                            JSONObject send = JSONObject.parseObject(sends.get(j).toString());
                            WorkMassContactEntity entity = new WorkMassContactEntity();
                            entity.setMassId(one.getId());
                            entity.setExternalUserid(send.getString("external_userid"));
                            try {
                                entity.setSendTime(LocalDateTime.ofEpochSecond(send.getLong("send_time"),0, ZoneOffset.ofHours(8)));
                            }catch (NullPointerException e){
                                entity.setSendTime(null);
                            }
                            entity.setUserid(send.getString("userid"));
                            entity.setStatus(send.getInteger("status"));
                            entity.setChatId(send.getString("chat_id"));
                            workMassContactService.save(entity);
                        }

                    }
                });
            }

        }
        workUpdateTimeService.updateSynTime( CorpContextHolder.getCorpId(), TypeEnum.MASS_MSG);
    }

    public List<WorkMassContactGroupDto> synGroupMsgList(Integer types,long startTime,long endTime,long temp,List<WorkMassContactGroupDto> lists,long nowTime){
        Map<String, Object> groupMsg = new HashMap<>();
        groupMsg.put("chat_type",types == 1  ? "single" : "group");
        groupMsg.put("start_time", startTime);
        groupMsg.put("end_time",endTime);

        //获取企业的全部群发记录
        String groupmsgList = WxApiUtils.getGroupmsgList( CorpContextHolder.getCorpId(), JSONObject.toJSONString(groupMsg));
        WorkMassContactGroupDto dto = new WorkMassContactGroupDto();
        dto.setText(groupmsgList);
        dto.setEndTime(endTime);
        dto.setStartTime(startTime);
        lists.add(dto);
        if (nowTime > endTime){
                startTime = temp;
                DateTime date = DateUtil.date(endTime * 1000);
                if (DateUtil.offsetDay(date, 30).getTime() > DateTime.now().getTime()){
                    endTime = DateTime.now().getTime() / 1000;
                }else {
                    endTime = DateUtil.offsetDay(date, 30).getTime() / 1000;
                }
                temp = endTime;
                return synGroupMsgList(types,startTime,endTime,temp,lists,nowTime);
        }

        return lists;
    }

    @Override
    public Page<List<WorkMassMsgPageVO>> getPageList(Page page, WorkMassMsgPageDTO dto) {
        SubPage subPage = new SubPage();
        HashMap<String, Object> map = new HashMap<>();
        map.put("updateTimeByMassMsg",workUpdateTimeService.getLastUpdateTime(TypeEnum.MASS_MSG));
        subPage.setExtraProps(map);

        QueryWrapper<WorkMassMsgEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("msg_type",dto.getMsgType()).orderByDesc("create_time");
        wrapper.eq("corp_id", CorpContextHolder.getCorpId());
        if (!StringUtil.isBlank(dto.getStartTime()) && !StringUtil.isBlank(dto.getEndTime())){
            wrapper.gt("send_time",dto.getStartTime()+" 00:00:00");
            wrapper.lt("send_time",dto.getEndTime()+" 23:59:59");
        }
        if (dto.getDept() != null){
            List<String> employeeWxList = new LinkedList<>();
            dto.getDept().forEach(d->{
                List<Integer> descendantList = (List<Integer>) remoteDeptService.getDescendantList(d).getData();
                List<Integer> wxDeptIds = (List<Integer>) remoteDeptService.getWxDeptIds(descendantList).getData();
                List<Integer> workDeptIds = workDeptService.list(new LambdaQueryWrapper<WorkDeptEntity>()
                        .eq(WorkDeptEntity::getCorpId, CorpContextHolder.getCorpId())
                        .in(WorkDeptEntity::getWxDepartmentId, wxDeptIds))
                        .stream()
                        .map(WorkDeptEntity::getId)
                        .collect(Collectors.toList());
                List<Integer> employeeIds = workEmployeeDepartmentService.getEmployeeIdsByDepts(workDeptIds);
                List<String> wxEmpIds = workEmployeeService.getWxEmpIdListByEmpIdList(employeeIds);
                employeeWxList.addAll(wxEmpIds);
            });
            if (employeeWxList.isEmpty()) {
                return subPage;
            }
            wrapper.in("creator",employeeWxList);

            //分割线
//            List<WorkEmployeeDepartmentEntity> list = workEmployeeDepartmentService.getDeptEmployeeList(dto.getDept());
//            List<Integer> employee = new LinkedList<>();
//            list.forEach(l ->{
//                employee.add(l.getEmployeeId());
//            });
//
//            List<WorkEmployeeEntity> employeeEntities = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
//                    .eq(WorkEmployeeEntity::getCorpId, CorpContextHolder.getCorpId())
//                    .in(WorkEmployeeEntity::getId, employee));
//
//            List<String> employeeWxList   = new LinkedList<>();
//            employeeEntities.forEach(e ->{
//                employeeWxList.add(e.getWxUserId());
//            });
//
//            wrapper.in("creator",employeeWxList);
        }

        if (dto.getEmployee() != null){
            List<WorkEmployeeEntity> employeeEntities = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .in(WorkEmployeeEntity::getId, dto.getEmployee())
                    .eq(WorkEmployeeEntity::getCorpId, CorpContextHolder.getCorpId()));

            List<String> employeeWxList   = new LinkedList<>();
            employeeEntities.forEach(e ->{
                employeeWxList.add(e.getWxUserId());
            });

            wrapper.in("creator",employeeWxList);
        }
        List<WorkMassMsgEntity> list = list(wrapper);
        List<WorkMassMsgPageVO> msgPageVOS = new LinkedList<>();
        list.forEach(r ->{
            WorkMassMsgPageVO pageVO = new WorkMassMsgPageVO();
            WorkEmployeeEntity one = workEmployeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .eq(WorkEmployeeEntity::getWxUserId, r.getCreator())
                    .eq(WorkEmployeeEntity::getCorpId, CorpContextHolder.getCorpId()));
            if (one != null){
                pageVO.setCreateId(r.getCreator());
                pageVO.setCreator(one.getName());
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                pageVO.setSendTime(df.format(r.getSendTime()));
                String[] split = r.getType().split(",");
                List<String> collect = Arrays.stream(split).collect(Collectors.toList());
                StringBuilder sb = new StringBuilder();
                collect.forEach(c ->{
                    switch (c){
                        case "1":
                            sb.append("文字").append("+");
                            break;
                        case "2":
                            sb.append("图片").append("+");
                            break;
                        case "3":
                            sb.append("链接").append("+");
                            break;
                        case "4":
                            sb.append("小程序").append("+");
                            break;
                        case "5":
                            sb.append("视频").append("+");
                            break;
                    }
                });
                pageVO.setMessageType(sb.toString().substring(0, sb.toString().length() - 1));
                pageVO.setDeliveryCount(r.getDeliveryCount());
                pageVO.setLoseCount(r.getLoseCount());
                pageVO.setId(r.getId());
                msgPageVOS.add(pageVO);
            }
        });
        msgPageVOS.sort(Comparator.comparing(WorkMassMsgPageVO::getSendTime).reversed());
        Page<WorkMassMsgPageVO> split = PageUtil.split(msgPageVOS, (int) page.getCurrent(), (int) page.getSize());
        subPage.setRecords(split.getRecords());
        subPage.setCurrent(split.getCurrent());
        subPage.setPages(split.getPages());
        subPage.setSize(split.getSize());
        subPage.setTotal(split.getTotal());
        return subPage;
    }

    @Override
    public WorkMassMsgDetailsVO getDetailsByMassId(Integer massId) {
        WorkMassMsgDetailsVO detailsVO = new WorkMassMsgDetailsVO();
        WorkMassMsgEntity msgEntity = getOne(Wrappers.<WorkMassMsgEntity>lambdaQuery()
                .eq(WorkMassMsgEntity::getId, massId)
                .eq(WorkMassMsgEntity::getCorpId, CorpContextHolder.getCorpId()));
        String[] split = msgEntity.getType().split(",");
        List<String> collect = Arrays.stream(split).collect(Collectors.toList());
        StringBuilder sb = new StringBuilder();
        collect.forEach(c ->{
            switch (c){
                case "1":
                    sb.append("文字").append("+");
                    break;
                case "2":
                    sb.append("图片").append("+");
                    break;
                case "3":
                    sb.append("链接").append("+");
                    break;
                case "4":
                    sb.append("小程序").append("+");
                    break;
                case "5":
                    sb.append("视频").append("+");
                    break;
            }
        });
        WorkEmployeeEntity employeeEntity = workEmployeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                .eq(WorkEmployeeEntity::getWxUserId, msgEntity.getCreator())
                .eq(WorkEmployeeEntity::getCorpId, CorpContextHolder.getCorpId()));

        List<WorkMassContactEntity> contactEntities = workMassContactService.list(Wrappers.<WorkMassContactEntity>lambdaQuery()
                .eq(WorkMassContactEntity::getMassId, msgEntity.getId()));

        StringBuilder client = new StringBuilder();
        AtomicBoolean flag = new AtomicBoolean(false);
        List<String> list = new LinkedList<>();
        contactEntities.forEach( c ->{
            if (!StringUtil.isBlank(c.getExternalUserid())){
                WorkContactEntity contactEntity = contactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery()
                        .eq(WorkContactEntity::getWxExternalUserid, c.getExternalUserid())
                        .eq(WorkContactEntity::getCorpId, CorpContextHolder.getCorpId()));
                client.append(contactEntity.getName()).append(",");
                list.add(contactEntity.getName());
                flag.set(true);
            }else {
                WorkRoomEntity roomServiceOne = workRoomService.getOne(Wrappers.<WorkRoomEntity>lambdaQuery()
                        .eq(WorkRoomEntity::getWxChatId, c.getChatId())
                        .eq(WorkRoomEntity::getCorpId, CorpContextHolder.getCorpId()));
                if (roomServiceOne != null){
                    client.append(roomServiceOne.getName()).append(",");
                    list.add(roomServiceOne.getName());
                }
            }

        });

        detailsVO.setMessageType(sb.toString().substring(0, sb.toString().length() - 1));
        detailsVO.setId(massId);
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        detailsVO.setSendTime(df.format(msgEntity.getSendTime()));
        detailsVO.setCreator(employeeEntity.getName());
        detailsVO.setCreateId(msgEntity.getCreator());
        String format = null;
        if (flag.get()){
            if (!StrUtil.isBlank(client)){
                String substring = client.toString().substring(0, client.toString().length() - 1);
                String[] strings = substring.split(",");
                if (strings.length>1){
                    format = String.format("【%s】、【%s】等%s个客户", strings[0], strings[1], strings.length);
                }else {
                    format = String.format("【%s】等%s个客户", strings[0],  strings.length);
                }
            }
        }else {
            if (!StrUtil.isBlank(client)){
                String substring = client.toString().substring(0, client.toString().length() - 1);
                String[] strings = substring.split(",");
                if (strings.length>1){
                    format = String.format("【%s】、【%s】等%s个群聊", strings[0], strings[1], strings.length);
                }else {
                    format = String.format("【%s】等%s个群聊", strings[0],  strings.length);
                }
            }
        }
        detailsVO.setSendMsg(format);
        detailsVO.setSendList(list);

        return detailsVO;
    }

    @Override
    public Page<List<WorkMassMsgDetailsListVO>> getDetailsByMassIdList(WorkMassMsgDetailsPageDTO dto, Page page) {
        QueryWrapper<WorkMassContactEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("mass_id",dto.getMassId()).orderByDesc("create_time");
        if (dto.getStatus() != null){
            wrapper.eq("status",dto.getStatus());
        }
        IPage<WorkMassContactEntity> iPage = workMassContactService.page(page, wrapper);
        List<WorkMassContactEntity> records = iPage.getRecords();

        List<WorkMassMsgDetailsListVO> listVOS = new LinkedList<>();
        if (!records.isEmpty()){

            records.forEach(r ->{
                WorkEmployeeEntity employeeEntity = workEmployeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .in(WorkEmployeeEntity::getWxUserId, r.getUserid())
                        .eq(WorkEmployeeEntity::getCorpId, CorpContextHolder.getCorpId()));
                if (employeeEntity == null){
                    return;
                }
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                WorkMassMsgDetailsListVO listVO = new WorkMassMsgDetailsListVO();
                if (!StringUtil.isBlank(dto.getRoomName()) || !StringUtil.isBlank(dto.getContactName())){

                    if (!StringUtil.isBlank(dto.getContactName())){
                        List<WorkContactEntity> contactEntities = contactService.list(Wrappers.<WorkContactEntity>lambdaQuery()
                                .eq(WorkContactEntity::getCorpId, CorpContextHolder.getCorpId())
                                .like(WorkContactEntity::getName, dto.getContactName()));
                        contactEntities.forEach(c ->{
                            if (c.getWxExternalUserid().equals(r.getExternalUserid())){
                                if (r.getSendTime() != null){
                                    listVO.setSendTime(df.format(r.getSendTime()));
                                }
                                listVO.setCreator(employeeEntity.getName());
                                listVO.setEmployeeId(employeeEntity.getId());
                                listVO.setCreateId(r.getUserid());
                                listVO.setName(c.getName());
                                listVO.setType(c.getType());
                                listVO.setTypeText(c.getType() == 1 ? "微信" : c.getCorpName());
                                listVO.setContactId(c.getId());
                                listVO.setStatus(r.getStatus());
                                listVO.setStatusText(WorkMassEnum.getTypeByCode(r.getStatus()));
                                String custNo = "";
                                WorkContactEmployeeEntity contactEmployeeEntity = workContactEmployeeService.getOne(new LambdaQueryWrapper<WorkContactEmployeeEntity>()
                                        .eq(WorkContactEmployeeEntity::getCorpId, CorpContextHolder.getCorpId())
                                        .eq(WorkContactEmployeeEntity::getEmployeeId, employeeEntity.getId())
                                        .eq(WorkContactEmployeeEntity::getContactId, c.getId()));
                                if (contactEmployeeEntity != null) {
                                    String remarkMobiles = contactEmployeeEntity.getRemarkMobiles();
                                    if (!JSONArray.parseArray(remarkMobiles).isEmpty()) {
                                        CrmCustomQueryConditionDTO queryCondition = new CrmCustomQueryConditionDTO();
                                        queryCondition.setMobileTel(JSONArray.parseArray(remarkMobiles).get(0).toString());
                                        List<WorkCustomInfoEntity> workCustomInfoEntitys = workCustomInfoService.listByCondition(queryCondition);
                                        custNo = workCustomInfoEntitys.isEmpty() ? "" : workCustomInfoEntitys.get(0).getCustNo();
                                    }
                                }
                                listVO.setCustNo(custNo);
                            }
                        });
                    }
                    if (!StringUtil.isBlank(dto.getRoomName())){
                        List<WorkRoomEntity> roomEntities = workRoomService.list(Wrappers.<WorkRoomEntity>lambdaQuery()
                                .eq(WorkRoomEntity::getCorpId, CorpContextHolder.getCorpId())
                                .like(WorkRoomEntity::getName, dto.getRoomName()));

                        roomEntities.forEach( roomEntity ->{
                            if (roomEntity.getWxChatId().equals(r.getChatId())){
                                if (r.getSendTime() != null){
                                    listVO.setSendTime(df.format(r.getSendTime()));
                                }
                                listVO.setCreator(employeeEntity.getName());
                                listVO.setCreateId(r.getUserid());
                                listVO.setName(roomEntity.getName());
                                listVO.setStatus(r.getStatus());
                                listVO.setStatusText(WorkMassEnum.getTypeByCode(r.getStatus()));
                                listVO.setContactId(roomEntity.getId());
                            }
                        });
                    }

                }else {
                    if (!StringUtil.isBlank(r.getExternalUserid())){
                        WorkContactEntity contactEntity = contactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery()
                                .eq(WorkContactEntity::getWxExternalUserid, r.getExternalUserid())
                                .eq(WorkContactEntity::getCorpId, CorpContextHolder.getCorpId()));
                        if (contactEntity != null){
                            if (r.getSendTime() != null){
                                listVO.setSendTime(df.format(r.getSendTime()));
                            }
                            listVO.setCreator(employeeEntity.getName());
                            listVO.setCreateId(r.getUserid());
                            listVO.setEmployeeId(employeeEntity.getId());
                            listVO.setName(contactEntity.getName());
                            listVO.setType(contactEntity.getType());
                            listVO.setTypeText(contactEntity.getType() == 1? "微信" : contactEntity.getCorpName());
                            listVO.setContactId(contactEntity.getId());
                            listVO.setStatus(r.getStatus());
                            listVO.setStatusText(WorkMassEnum.getTypeByCode(r.getStatus()));
                            String custNo = "";
                            WorkContactEmployeeEntity contactEmployeeEntity = workContactEmployeeService.getOne(new LambdaQueryWrapper<WorkContactEmployeeEntity>()
                                    .eq(WorkContactEmployeeEntity::getCorpId, CorpContextHolder.getCorpId())
                                    .eq(WorkContactEmployeeEntity::getEmployeeId, employeeEntity.getId())
                                    .eq(WorkContactEmployeeEntity::getContactId, contactEntity.getId()));
                            if (contactEmployeeEntity == null) {
                                listVOS.add(listVO);
                                return;
                            } else {
                                String remarkMobiles = contactEmployeeEntity.getRemarkMobiles();
                                if (!JSONArray.parseArray(remarkMobiles).isEmpty()) {
                                    CrmCustomQueryConditionDTO queryCondition = new CrmCustomQueryConditionDTO();
                                    queryCondition.setMobileTel(JSONArray.parseArray(remarkMobiles).get(0).toString());
                                    List<WorkCustomInfoEntity> workCustomInfoEntitys = workCustomInfoService.listByCondition(queryCondition);
                                    custNo = workCustomInfoEntitys.isEmpty() ? "" : workCustomInfoEntitys.get(0).getCustNo();
                                }
                                listVO.setCustNo(custNo);
                            }

                        }
                    }else {
                        WorkRoomEntity roomEntity = workRoomService.getOne(Wrappers.<WorkRoomEntity>lambdaQuery()
                                .eq(WorkRoomEntity::getWxChatId, r.getChatId())
                                .eq(WorkRoomEntity::getCorpId, CorpContextHolder.getCorpId()));
                        if (roomEntity != null){
                            if (r.getSendTime() != null){
                                listVO.setSendTime(df.format(r.getSendTime()));
                            }
                            listVO.setCreator(employeeEntity.getName());
                            listVO.setCreateId(r.getUserid());
                            listVO.setName(roomEntity.getName());
                            listVO.setStatus(r.getStatus());
                            listVO.setStatusText(WorkMassEnum.getTypeByCode(r.getStatus()));
                            listVO.setContactId(roomEntity.getId());
                        }
                    }
                }
                if (listVO.getContactId() != null){
                    listVOS.add(listVO);
                }
            });
        }


        SubPage subPage = new SubPage();
        subPage.setTotal(listVOS.size());
        subPage.setCurrent(iPage.getCurrent());
        subPage.setRecords(listVOS);
        subPage.setSize(iPage.getSize());
        subPage.setPages(iPage.getPages());
        HashMap<String, Object> map = new HashMap<>();
        map.put("updateTimeByMassMsg",workUpdateTimeService.getLastUpdateTime(TypeEnum.MASS_MSG));
        subPage.setExtraProps(map);
        return subPage;
    }

    @Override
    public void exitExcelList(WorkMassMsgPageDTO dto, HttpServletResponse response, OutputStream out) {
        QueryWrapper<WorkMassMsgEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("msg_type",dto.getMsgType()).orderByDesc("create_time");
        wrapper.eq("corp_id", CorpContextHolder.getCorpId());
        if (!StringUtil.isBlank(dto.getStartTime()) && !StringUtil.isBlank(dto.getEndTime())){
            wrapper.gt("create_time",dto.getStartTime()+" 00:00:00");
            wrapper.lt("create_time",dto.getEndTime()+" 23:59:59");
        }
        if (dto.getDept() != null){
            List<WorkEmployeeDepartmentEntity> list = workEmployeeDepartmentService.getDeptEmployeeList(dto.getDept());
            List<Integer> employee = new LinkedList<>();
            list.forEach(l ->{
                employee.add(l.getEmployeeId());
            });

            List<WorkEmployeeEntity> employeeEntities = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .eq(WorkEmployeeEntity::getCorpId, CorpContextHolder.getCorpId())
                    .in(WorkEmployeeEntity::getId, employee));

            List<String> employeeWxList   = new LinkedList<>();
            employeeEntities.forEach(e ->{
                employeeWxList.add(e.getWxUserId());
            });

            wrapper.in("creator",employeeWxList);
        }

        if (dto.getEmployee() != null){
            List<WorkEmployeeEntity> employeeEntities = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .eq(WorkEmployeeEntity::getCorpId, CorpContextHolder.getCorpId())
                    .in(WorkEmployeeEntity::getId, dto.getEmployee()));

            List<String> employeeWxList   = new LinkedList<>();
            employeeEntities.forEach(e ->{
                employeeWxList.add(e.getWxUserId());
            });

            wrapper.in("creator",employeeWxList);
        }

        List<WorkMassMsgEntity> records = list(wrapper);
        List<WorkMassMsgExcelVO> msgPageVOS = new LinkedList<>();
        records.forEach(r ->{
            StringBuilder builder = new StringBuilder();
            WorkMassMsgExcelVO pageVO = new WorkMassMsgExcelVO();
            WorkEmployeeEntity one = workEmployeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .eq(WorkEmployeeEntity::getCorpId, CorpContextHolder.getCorpId())
                    .eq(WorkEmployeeEntity::getWxUserId, r.getCreator()));
            if (one != null){
                pageVO.setCreator(one.getName());
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                pageVO.setSendTime(df.format(r.getSendTime()));
                String[] split = r.getType().split(",");
                List<String> collect = Arrays.stream(split).collect(Collectors.toList());
                StringBuilder sb = new StringBuilder();
                collect.forEach(c ->{
                    switch (c){
                        case "1":
                            sb.append("文字").append("+");
                            break;
                        case "2":
                            sb.append("图片").append("+");
                            break;
                        case "3":
                            sb.append("链接").append("+");
                            break;
                        case "4":
                            sb.append("小程序").append("+");
                            break;
                        case "5":
                            sb.append("视频").append("+");
                            break;
                    }
                });
                List<WorkMassContactEntity> list = workMassContactService.list(Wrappers.<WorkMassContactEntity>lambdaQuery()
                        .eq(WorkMassContactEntity::getMassId, r.getId()));
                list.forEach(l ->{
                    if (dto.getMsgType() == 1){
                        WorkContactEntity contactEntity = contactService.getOne(Wrappers.<WorkContactEntity>lambdaQuery()
                                .eq(WorkContactEntity::getWxExternalUserid, l.getExternalUserid())
                                .eq(WorkContactEntity::getCorpId, CorpContextHolder.getCorpId()));
                        builder.append(contactEntity.getName()).append(",");
                    }else {
                        WorkRoomEntity roomEntity = workRoomService.getOne(Wrappers.<WorkRoomEntity>lambdaQuery()
                                .eq(WorkRoomEntity::getWxChatId, l.getChatId())
                                .eq(WorkRoomEntity::getCorpId, CorpContextHolder.getCorpId()));
                        if (roomEntity != null){
                            builder.append(roomEntity.getName()).append(",");
                        }
                    }
                });

                pageVO.setMessageType(sb.toString().substring(0, sb.toString().length() - 1));
                pageVO.setDeliveryCount(r.getDeliveryCount());
                pageVO.setLoseCount(r.getLoseCount());
                if (builder != null && !builder.toString().equals("")){
                    pageVO.setContacts(builder.toString().substring(0, builder.toString().length() - 1));
                }

                msgPageVOS.add(pageVO);
            }
        });
        if (dto.getMsgType() == 1){
            exitExcelByContact(msgPageVOS,response,out);
        }else {
            exitExcelByRoom(msgPageVOS,response,out);
        }

    }

    private void exitExcelByRoom(List<WorkMassMsgExcelVO> msgPageVOS, HttpServletResponse response, OutputStream out){
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<WorkMassMsgExcelVO> rows = CollUtil.newArrayList(msgPageVOS);

        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter();
        writer.autoSizeColumnAll();

        //自定义标题别名
        writer.addHeaderAlias("creator", "创建者");
        writer.addHeaderAlias("messageType", "消息类型");
        writer.addHeaderAlias("sendTime", "发送时间");
        writer.addHeaderAlias("contacts", "送达群聊");
        writer.addHeaderAlias("deliveryCount", "送达群聊数");
        writer.addHeaderAlias("loseCount", "发送失败群聊数");

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=room.xls");

        // 合并单元格后的标题行，使用默认标题样式
        //跳过一行
        writer.passCurrentRow();
        writer.passCurrentRow();
        writer.merge(0,1,0,5, "客户群群发列表（导出时间："+df.format(LocalDateTime.now())+"）",true);
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(rows, true);
        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();

        IoUtil.close(out);
    }


    private void exitExcelByContact(List<WorkMassMsgExcelVO> msgPageVOS, HttpServletResponse response, OutputStream out){
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<WorkMassMsgExcelVO> rows = CollUtil.newArrayList(msgPageVOS);

        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter();
        writer.autoSizeColumnAll();

        //自定义标题别名
        writer.addHeaderAlias("creator", "创建者");
        writer.addHeaderAlias("messageType", "消息类型");
        writer.addHeaderAlias("sendTime", "发送时间");
        writer.addHeaderAlias("contacts", "发送客户");
        writer.addHeaderAlias("deliveryCount", "送达客户数");
        writer.addHeaderAlias("loseCount", "发送失败客户数");

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=content.xls");
        // 合并单元格后的标题行，使用默认标题样式
        //跳过一行
        writer.passCurrentRow();
        writer.passCurrentRow();
        writer.merge(0,1,0,5, "个人群发记录列表（导出时间："+df.format(LocalDateTime.now())+"）",true);
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(rows, true);
        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();

        IoUtil.close(out);
    }


    private boolean getSendList(int deliveryCount,int lossCount,JSONObject sendResults,String userid,JSONArray sendList){
        if (!StringUtil.isBlank(sendResults.getString("next_cursor"))){
            Map<String, Object> send = new HashMap<>();
            send.put("msgid",sendResults.getString("msgid"));
            send.put("userid",userid);
            send.put("next_cursor",sendResults.getString("next_cursor"));
            String result = WxApiUtils.getGroupmsgSendResult( CorpContextHolder.getCorpId(), JSONObject.toJSONString(send));
            JSONObject sendResult = JSONObject.parseObject(result);
            JSONArray parseArray = JSONArray.parseArray(sendResult.getString("send_list"));
            for (int j = 0; j < parseArray.size(); j++) {
                JSONObject taskk = JSONObject.parseObject(parseArray.get(j).toString());
                if (taskk.getInteger("status").equals(2)){
                    deliveryCount++;
                }else {
                    lossCount++;
                }
            }
            return getSendList(deliveryCount,lossCount,sendResult,userid,sendList);
        }else {
            JSONArray parseArray = JSONArray.parseArray(sendResults.getString("send_list"));
            sendList.addAll(parseArray);
            return false;
        }
    }


    private boolean getTaskList(JSONObject taskResults,String msgid,JSONArray taskList){
        if (!StringUtil.isBlank(taskResults.getString("next_cursor"))){
                Map<String, Object> task = new HashMap<>();
                task.put("msgid",msgid);
                task.put("next_cursor",taskResults.getString("next_cursor"));

                String groupmsgTask = WxApiUtils.getGroupmsgTask( CorpContextHolder.getCorpId(), JSONObject.toJSONString(task));
                JSONObject taskResult = JSONObject.parseObject(groupmsgTask);
            return getTaskList(taskResult,msgid,taskList);
        }else {
            JSONArray list = JSONArray.parseArray(taskResults.getString("task_list"));
            taskList.addAll(list);
            return false;
        }
    }

    private boolean getGroupMsg(JSONObject groupResults,JSONArray groupList,long startTime,long endTime,Integer types){
        if (!StringUtil.isBlank(groupResults.getString("next_cursor"))){
            Map<String, Object> groupMsg = new HashMap<>();
            groupMsg.put("chat_type",types == 1  ? "single" : "group");
            groupMsg.put("start_time", startTime);
            groupMsg.put("end_time",endTime);
            groupMsg.put("next_cursor",groupResults.getString("next_cursor"));

            String groupesult = WxApiUtils.getGroupmsgList( CorpContextHolder.getCorpId(), JSONObject.toJSONString(groupMsg));
            JSONObject groupResulty = JSONObject.parseObject(groupesult);
            return getGroupMsg(groupResulty,groupList,startTime,endTime,types);
        }else {
            JSONArray groupMsgList = JSONArray.parseArray(groupResults.getString("group_msg_list"));
            groupList.addAll(groupMsgList);
            return false;
        }
    }
}
